package online.flowerinsnow.minecraft.bukkit.manhunt.manager.impl;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.CompassMeta;
import online.flowerinsnow.minecraft.bukkit.manhunt.Manhunt;
import online.flowerinsnow.minecraft.bukkit.manhunt.core.compass.ITrackingLocation;
import online.flowerinsnow.minecraft.bukkit.manhunt.manager.ICompassManager;
import online.flowerinsnow.minecraft.bukkit.manhunt.manager.ITeamManager;

import java.util.HashMap;
import java.util.Map;

public class CompassManagerImpl implements ICompassManager {
    private final Map<Player, Location> lastKnownLocation = new HashMap<>();
    private final Map<Player, Location> tracking = new HashMap<>();

    @Override
    public Location getPlayerTracking(Player player) {
        return tracking.get(player);
    }

    @Override
    public Location getLocationLodestone(Location location) {
        //noinspection ConstantConditions
        switch (location.getWorld().getEnvironment()) {
            case NORMAL -> {
                location = location.clone();
                location.setY(-63);
                location.getBlock().setType(Material.BEDROCK);
                location.setY(-64);
                location.getBlock().setType(Material.LODESTONE);
            }
            case NETHER -> {
                location = location.clone();
                location.setY(1);
                location.getBlock().setType(Material.BEDROCK);
                location.setY(0);
                location.getBlock().setType(Material.LODESTONE);
            }
            case THE_END -> {
                location = location.clone();
                location.setY(254);
                location.getBlock().setType(Material.BEDROCK);
                location.setY(255);
                location.getBlock().setType(Material.LODESTONE);
            }
        }
        return location;
    }

    @Override
    public void update() {
        Bukkit.getOnlinePlayers().forEach(p -> {
            if ("world".equals(p.getWorld().getName())) {
                setCompassTarget(p, (Location) null);
                return;
            }
            Location target = getPlayerTracking(p);
            setCompassTarget(p, target);
        });
    }

    @Override
    public void refresh() {
        Bukkit.getOnlinePlayers().forEach(this::refreshPlayer);
        /*
        Bukkit.getOnlinePlayers().forEach(p -> {
            if ("world".equals(p.getWorld().getName())) {
                tracking.remove(p);
                resetPlayerLastKnownLocation(p);
                return;
            }
            ITeamManager teamManager = Manhunt.getTeamManager();
            if (teamManager.getPlayerTeam(p) == PlayerTeam.HUNTER) {
                ITrackingLocation nearest = null; // 最近的目标
                double distance = Double.MAX_VALUE;
                for (Player target : teamManager.getRunners()) { // 遍历所有逃跑者
                    ITrackingLocation track;
                    if (p.getWorld() == target.getWorld()) {
                        track = TrackingLocationImpl.build(target);
                    } else {
                        Location loc = getPlayerLastKnownLocation(target);
                        if (loc == null || loc.getWorld() != p.getWorld()) return;
                        track = TrackingLocationImpl.build(target, loc, true);
                    }
                    double d = track.getLocation().distance(p.getLocation());
                    if (d < distance) {
                        nearest = track;
                        distance = d;
                    }
                }
                tracking.put(p, nearest);
            } else {
                tracking.put(p, null);
            }
        });
         */
    }
    private void refreshPlayer(Player player) {
        if ("world".equals(player.getWorld().getName())) {
            tracking.remove(player);
            return;
        }
        tracking.put(player, getNearestRunner(player));
    }
    private Location getNearestRunner(Player player) {
        ITeamManager teamManager = Manhunt.getTeamManager();
        if (!teamManager.isHunter(player)) return null;
        final Location[] nearest = new Location[1];
        final double[] distance = {Double.MAX_VALUE};
        teamManager.getRunners().forEach(p -> {
            Location l = p.getLocation();
            double d = p.getLocation().distance(l);
            if ((nearest[0] == null || distance[0] > d) && player.getWorld() == p.getWorld()) {
                nearest[0] = l;
                distance[0] = d;
            }
        });
        return nearest[0];
    }

    @SuppressWarnings("ConstantConditions")
    private void setCompassTarget(Player a, Location b) {
//        if (b != null) {
            // 显示距离
//            a.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(MessageUtils.parseColor("&7[&b!&7]&b跟踪目标: &e" + b.getPlayer().getName() +
//                    " &b距离: &e" + String.format("%.2f", b.distance(a.getLocation())))));
//        }
        // 遍历玩家背包 设置全部指南针效果
        PlayerInventory inv = a.getInventory();
        for (int i = 0; i < 41; i++) {
            ItemStack item = inv.getItem(i);
            if (item == null || item.getType() != Material.COMPASS) continue;
            CompassMeta meta = (CompassMeta) item.getItemMeta();
            if (b == null) {
                meta.setLodestoneTracked(false);
            } else {
                meta.setLodestoneTracked(true);
                meta.setLodestone(getLocationLodestone(b));
            }
            item.setItemMeta(meta);
        }
    }


    // 弃用方法

    @Override
    @Deprecated
    public Location getLodestone(ITrackingLocation tracking) {
        Location location = tracking.getLocation().clone();
        location.setY(1);
        location.getBlock().setType(Material.BEDROCK);
        location.setY(0);
        location.getBlock().setType(Material.LODESTONE);
        return location;
    }

    @Deprecated
    private void setCompassTarget(Player a, ITrackingLocation b) {
        setCompassTarget(a, b.getLocation());
    }

    @Override
    @Deprecated
    public Location getPlayerLastKnownLocation(Player player) {
        return lastKnownLocation.get(player);
    }

    @Override
    @Deprecated
    public void setPlayerLastKnownLocation(Player player, Location location) {
        lastKnownLocation.put(player, location);
    }

    @Override
    @Deprecated
    public void resetPlayerLastKnownLocation(Player player) {
        lastKnownLocation.remove(player);
    }

    @Override
    @Deprecated
    public void resetAllLastKnownLocation() {
        lastKnownLocation.clear();
    }

    @Override
    @Deprecated
    public ITrackingLocation getTracking(Player player) {
//        return tracking.get(player);
        throw new RuntimeException("方法已弃用 不支持继续调用");
    }

}
